home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / dev / lang / python_src.lha / amigapython / modules / posixmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-25  |  31.7 KB  |  1,667 lines

  1. /***********************************************************
  2. Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
  3. The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* POSIX module implementation */
  26.  
  27. /* This file is also used for Windows NT.  In that case the module
  28.    actually calls itself 'nt', not 'posix', and a few functions are
  29.    either unimplemented or implemented differently.  The source
  30.    assumes that for Windows NT, the macro 'NT' is defined independent
  31.    of the compiler used.  Different compilers define their own feature
  32.    test macro, e.g. '__BORLANDC__' or '_MSCVER'. */
  33.  
  34. /* For MS-DOS and Windows 3.x, use ../Dos/dosmodule.c */
  35.  
  36. #include "allobjects.h"
  37. #include "modsupport.h"
  38. #include "ceval.h"
  39.  
  40. #include <string.h>
  41. #include <errno.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #ifdef HAVE_SYS_WAIT_H
  45. #include <sys/wait.h>        /* For WNOHANG */
  46. #endif
  47.  
  48. #ifdef __SASC
  49. #include <proto/dos.h>
  50. #include <dos.h>
  51. #endif
  52.  
  53. #include "mytime.h"        /* For clock_t on some systems */
  54.  
  55. #ifdef HAVE_FCNTL_H
  56. #include <fcntl.h>
  57. #endif /* HAVE_FCNTL_H */
  58.  
  59. #ifndef NT
  60. #define HAVE_FORK    1
  61. #endif
  62.  
  63. #if !defined(NT) || defined(__BORLANDC__)
  64. /* Unix functions that the configure script doesn't check for
  65.    and that aren't easily available under NT except with Borland C */
  66. #define HAVE_GETEGID    1
  67. #define HAVE_GETEUID    1
  68. #define HAVE_GETGID    1
  69. #define HAVE_GETPPID    1
  70. #define HAVE_GETUID    1
  71. #define HAVE_KILL    1
  72. #define HAVE_WAIT    1
  73. #define HAVE_OPENDIR    1
  74. #define HAVE_PIPE    1
  75. #define HAVE_GETCWD    1
  76. #endif
  77.  
  78. #ifndef NT
  79.  
  80. #ifdef HAVE_UNISTD_H
  81. #include <unistd.h>
  82. #endif
  83.  
  84. #ifdef NeXT
  85. /* NeXT's <unistd.h> and <utime.h> aren't worth much */
  86. #undef HAVE_UNISTD_H
  87. #undef HAVE_UTIME_H
  88. /* #undef HAVE_GETCWD */
  89. #endif
  90.  
  91. #ifdef HAVE_UNISTD_H
  92. /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
  93. extern int rename();
  94. extern int pclose();
  95. extern int lstat();
  96. extern int symlink();
  97. #else /* !HAVE_UNISTD_H */
  98. extern int mkdir PROTO((const char *, mode_t));
  99. extern int chdir PROTO((const char *));
  100. extern int rmdir PROTO((const char *));
  101. extern int chmod PROTO((const char *, mode_t));
  102. extern int chown PROTO((const char *, uid_t, gid_t));
  103. extern char *getcwd PROTO((char *, int));
  104. extern char *strerror PROTO((int));
  105. extern int link PROTO((const char *, const char *));
  106. extern int rename PROTO((const char *, const char *));
  107. extern int stat PROTO((const char *, struct stat *));
  108. extern int unlink PROTO((const char *));
  109. extern int pclose PROTO((FILE *));
  110. #ifdef HAVE_SYMLINK
  111. extern int symlink PROTO((const char *, const char *));
  112. #endif /* HAVE_SYMLINK */
  113. #ifdef HAVE_LSTAT
  114. extern int lstat PROTO((const char *, struct stat *));
  115. #endif /* HAVE_LSTAT */
  116. #endif /* !HAVE_UNISTD_H */
  117.  
  118. #endif /* !NT */
  119.  
  120. #ifdef HAVE_UTIME_H
  121. #include <utime.h>
  122. #endif /* HAVE_UTIME_H */
  123.  
  124. #ifdef HAVE_SYS_UTIME_H
  125. #include <sys/utime.h>
  126. #define HAVE_UTIME_H /* pretend we do for the rest of this file */
  127. #endif /* HAVE_SYS_UTIME_H */
  128.  
  129. #ifdef HAVE_SYS_TIMES_H
  130. #include <sys/times.h>
  131. #endif /* HAVE_SYS_TIMES_H */
  132.  
  133. #ifdef HAVE_SYS_PARAM_H
  134. #include <sys/param.h>
  135. #endif /* HAVE_SYS_PARAM_H */
  136.  
  137. #ifdef HAVE_SYS_UTSNAME_H
  138. #include <sys/utsname.h>
  139. #endif /* HAVE_SYS_UTSNAME_H */
  140.  
  141. #ifndef MAXPATHLEN
  142. #define MAXPATHLEN 1024
  143. #endif /* MAXPATHLEN */
  144.  
  145. #ifdef HAVE_DIRENT_H
  146. #include <dirent.h>
  147. #define NAMLEN(dirent) strlen((dirent)->d_name)
  148. #else
  149. #define dirent direct
  150. #define NAMLEN(dirent) (dirent)->d_namlen
  151. #ifdef HAVE_SYS_NDIR_H
  152. #include <sys/ndir.h>
  153. #endif
  154. #ifdef HAVE_SYS_DIR_H
  155. #include <sys/dir.h>
  156. #endif
  157. #ifdef HAVE_NDIR_H
  158. #include <ndir.h>
  159. #endif
  160. #endif
  161.  
  162. #ifdef NT
  163. #include <direct.h>
  164. #include <io.h>
  165. #include <process.h>
  166. #include <windows.h>
  167. #define popen   _popen
  168. #define pclose    _pclose
  169. #endif /* NT */
  170.  
  171. #ifdef OS2
  172. #include <io.h>
  173. #endif /* OS2 */
  174.  
  175. /* Return a dictionary corresponding to the POSIX environment table */
  176.  
  177. #ifdef AMIGA
  178. #undef HAVE_FORK
  179. #undef HAVE_UTIME_H
  180. #undef HAVE_GETPID
  181. #undef HAVE_GETEGID
  182. #undef HAVE_GETEUID
  183. #undef HAVE_GETGID
  184. #undef HAVE_GETPPID
  185. #undef HAVE_GETUID
  186. #undef HAVE_KILL
  187. #undef HAVE_WAIT
  188. #undef HAVE_PIPE
  189.  
  190. char **environ;
  191. #endif /* AMIGA */
  192.  
  193. #ifndef NT
  194. extern char **environ;
  195. #endif /* !NT */
  196.  
  197. static object *
  198. convertenviron()
  199. {
  200. #ifdef AMIGA
  201.     struct FileInfoBlock *fib;
  202.     int nread;
  203. #define RBUFSIZE 128
  204.     char *rbuf;
  205.     BPTR fl,fh;
  206.     int environSize;
  207. #endif
  208.     object *d;
  209.     char **e;
  210.     d = newdictobject();
  211.     if (d == NULL)
  212.         return NULL;
  213. #ifdef AMIGA
  214.     // construct the environ array from the files in ENV:
  215.     environSize = 0;
  216.  
  217.     if ((fib = (struct FileInfoBlock *)
  218.         malloc(sizeof (struct FileInfoBlock))) == NULL) {
  219.         fatal("No memory for FileInfoBlock");
  220.     }
  221.     if ((rbuf = (char *)malloc(RBUFSIZE)) == NULL) {
  222.         fatal("No memory for Read buffer");
  223.     }
  224. #define NUMENVVARS 128
  225.     if ((environ = (char **)
  226.         malloc(NUMENVVARS * sizeof (char *))) == NULL) {
  227.         fatal("No memory for environ pointer array");
  228.     }
  229.  
  230.     if ((fl = Lock("ENV:", ACCESS_READ)) == NULL) {
  231.         fatal("Strange, couldn't find ENV:");
  232.     }
  233.     if (Examine(fl, fib) == DOSFALSE) {
  234.         fatal("Something wrong with ENV:");
  235.     }
  236.     // environSize is zero
  237.     while (ExNext(fl, fib) != DOSFALSE) {
  238.         if (fib->fib_Size > RBUFSIZE ||
  239.             fib->fib_DirEntryType >= 0) continue; // can't be an env var
  240.         strcpy(rbuf, "ENV:");    // All right I'm double using a string buf
  241.         strcat(rbuf, fib->fib_FileName);
  242.         fh = Open(rbuf, MODE_OLDFILE); // must succeed :-)
  243.         if (fh == NULL) {
  244.             fatal("Couldn't read from ENV file");
  245.         }
  246.         if ((nread = Read(fh, rbuf, RBUFSIZE)) > 0) {
  247.             rbuf[nread] = '\0';
  248.             environ[environSize] =
  249.                 (char *)malloc(strlen(fib->fib_FileName) + nread + 2);
  250.             if (environ[environSize] == NULL) {
  251.                 fatal("Out of memory allocating for env var");
  252.             }
  253.             strcpy(environ[environSize], fib->fib_FileName);
  254.             strcat(environ[environSize], "=");
  255.             strcat(environ[environSize], rbuf);
  256.             environSize++;
  257.         } else {
  258.             fatal("Couldn't read from ENV file");
  259.         }
  260.         Close(fh);
  261.     }
  262.     UnLock(fl);
  263.     if (IoErr() != ERROR_NO_MORE_ENTRIES) {
  264.         fatal("Something wrong with env:var");
  265.     }
  266.  
  267.     environ[environSize] = NULL;
  268.  
  269.     free(rbuf);
  270.     free(fib);
  271. #endif /* AMIGA */
  272.     if (environ == NULL)
  273.         return d;
  274.     /* XXX This part ignores errors */
  275.     for (e = environ; *e != NULL; e++) {
  276.         object *v;
  277.         char *p = strchr(*e, '=');
  278.         if (p == NULL)
  279.             continue;
  280.         v = newstringobject(p+1);
  281.         if (v == NULL)
  282.             continue;
  283.         *p = '\0';
  284.         (void) dictinsert(d, *e, v);
  285.         *p = '=';
  286.         DECREF(v);
  287.     }
  288.     return d;
  289. }
  290.  
  291.  
  292. static object *PosixError; /* Exception posix.error */
  293.  
  294. /* Set a POSIX-specific error from errno, and return NULL */
  295.  
  296. static object * posix_error()
  297. {
  298.     return err_errno(PosixError);
  299. }
  300.  
  301.  
  302. /* POSIX generic methods */
  303.  
  304. static object *
  305. posix_1str(args, func)
  306.     object *args;
  307.     int (*func) FPROTO((const char *));
  308. {
  309.     char *path1;
  310.     int res;
  311.     if (!getargs(args, "s", &path1))
  312.         return NULL;
  313.     BGN_SAVE
  314.     res = (*func)(path1);
  315.     END_SAVE
  316.     if (res < 0)
  317.         return posix_error();
  318.     INCREF(None);
  319.     return None;
  320. }
  321.  
  322. static object *
  323. posix_2str(args, func)
  324.     object *args;
  325.     int (*func) FPROTO((const char *, const char *));
  326. {
  327.     char *path1, *path2;
  328.     int res;
  329.     if (!getargs(args, "(ss)", &path1, &path2))
  330.         return NULL;
  331.     BGN_SAVE
  332.     res = (*func)(path1, path2);
  333.     END_SAVE
  334.     if (res < 0)
  335.         return posix_error();
  336.     INCREF(None);
  337.     return None;
  338. }
  339.  
  340. static object *
  341. posix_strint(args, func)
  342.     object *args;
  343.     int (*func) FPROTO((const char *, int));
  344. {
  345.     char *path;
  346.     int i;
  347.     int res;
  348.     if (!getargs(args, "(si)", &path, &i))
  349.         return NULL;
  350.     BGN_SAVE
  351.     res = (*func)(path, i);
  352.     END_SAVE
  353.     if (res < 0)
  354.         return posix_error();
  355.     INCREF(None);
  356.     return None;
  357. }
  358.  
  359. static object *
  360. posix_strintint(args, func)
  361.     object *args;
  362.     int (*func) FPROTO((const char *, int, int));
  363. {
  364.     char *path;
  365.     int i,i2;
  366.     int res;
  367.     if (!getargs(args, "(sii)", &path, &i, &i2))
  368.         return NULL;
  369.     BGN_SAVE
  370.     res = (*func)(path, i, i2);
  371.     END_SAVE
  372.     if (res < 0)
  373.         return posix_error();
  374.     INCREF(None);
  375.     return None;
  376. }
  377.  
  378. static object *
  379. posix_do_stat(self, args, statfunc)
  380.     object *self;
  381.     object *args;
  382.     int (*statfunc) FPROTO((const char *, struct stat *));
  383. {
  384.     struct stat st;
  385.     char *path;
  386.     int res;
  387.     if (!getargs(args, "s", &path))
  388.         return NULL;
  389.     BGN_SAVE
  390.     res = (*statfunc)(path, &st);
  391.     END_SAVE
  392.     if (res != 0)
  393.         return posix_error();
  394.     return mkvalue("(llllllllll)",
  395.             (long)st.st_mode,
  396.             (long)st.st_ino,
  397.             (long)st.st_dev,
  398.             (long)st.st_nlink,
  399.             (long)st.st_uid,
  400.             (long)st.st_gid,
  401.             (long)st.st_size,
  402.             (long)st.st_atime,
  403.             (long)st.st_mtime,
  404.             (long)st.st_ctime);
  405. }
  406.  
  407.  
  408. /* POSIX methods */
  409.  
  410. static object *
  411. posix_chdir(self, args)
  412.     object *self;
  413.     object *args;
  414. {
  415.     return posix_1str(args, chdir);
  416. }
  417.  
  418. static object *
  419. posix_chmod(self, args)
  420.     object *self;
  421.     object *args;
  422. {
  423.     return posix_strint(args, chmod);
  424. }
  425.  
  426. #ifdef HAVE_CHOWN
  427. static object *
  428. posix_chown(self, args)
  429.     object *self;
  430.     object *args;
  431. {
  432.     return posix_strintint(args, chown);
  433. }
  434. #endif /* HAVE_CHOWN */
  435.  
  436. #ifdef HAVE_GETCWD
  437. static object *
  438. posix_getcwd(self, args)
  439.     object *self;
  440.     object *args;
  441. {
  442.     char buf[1026];
  443.     char *res;
  444.     if (!getnoarg(args))
  445.         return NULL;
  446.     BGN_SAVE
  447.     res = getcwd(buf, sizeof buf);
  448.     END_SAVE
  449.     if (res == NULL)
  450.         return posix_error();
  451.     return newstringobject(buf);
  452. }
  453. #endif
  454.  
  455. #ifdef HAVE_LINK
  456. static object *
  457. posix_link(self, args)
  458.     object *self;
  459.     object *args;
  460. {
  461.     return posix_2str(args, link);
  462. }
  463. #endif /* HAVE_LINK */
  464.  
  465. static object *
  466. posix_listdir(self, args)
  467.     object *self;
  468.     object *args;
  469. {
  470. #if defined(NT) && !defined(HAVE_OPENDIR)
  471.  
  472.     char *name;
  473.     int len;
  474.     object *d, *v;
  475.     HANDLE hFindFile;
  476.     WIN32_FIND_DATA FileData;
  477.     char namebuf[MAX_PATH+5];
  478.  
  479.     if (!getargs(args, "s#", &name, &len))
  480.         return NULL;
  481.     if (len >= MAX_PATH) {
  482.         err_setstr(ValueError, "path too long");
  483.         return NULL;
  484.     }
  485.     strcpy(namebuf, name);
  486.     if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  487.         namebuf[len++] = '/';
  488.     strcpy(namebuf + len, "*.*");
  489.  
  490.     if ((d = newlistobject(0)) == NULL)
  491.         return NULL;
  492.  
  493.     hFindFile = FindFirstFile(namebuf, &FileData);
  494.     if (hFindFile == INVALID_HANDLE_VALUE) {
  495.         errno = GetLastError();
  496.         return posix_error();
  497.     }
  498.     do {
  499.         if (FileData.cFileName[0] == '.' &&
  500.             (FileData.cFileName[1] == '\0' ||
  501.              FileData.cFileName[1] == '.' &&
  502.              FileData.cFileName[2] == '\0'))
  503.             continue;
  504.         v = newstringobject(FileData.cFileName);
  505.         if (v == NULL) {
  506.             DECREF(d);
  507.             d = NULL;
  508.             break;
  509.         }
  510.         if (addlistitem(d, v) != 0) {
  511.             DECREF(v);
  512.             DECREF(d);
  513.             d = NULL;
  514.             break;
  515.         }
  516.         DECREF(v);
  517.     } while (FindNextFile(hFindFile, &FileData) == TRUE);
  518.  
  519.     if (FindClose(hFindFile) == FALSE) {
  520.         errno = GetLastError();
  521.         return posix_error();
  522.     }
  523.  
  524.     return d;
  525.  
  526. #else /* !NT */
  527.  
  528.     char *name;
  529.     object *d, *v;
  530.     DIR *dirp;
  531.     struct dirent *ep;
  532.     if (!getargs(args, "s", &name))
  533.         return NULL;
  534.     BGN_SAVE
  535.     if ((dirp = opendir(name)) == NULL) {
  536.         RET_SAVE
  537.         return posix_error();
  538.     }
  539.     if ((d = newlistobject(0)) == NULL) {
  540.         closedir(dirp);
  541.         RET_SAVE
  542.         return NULL;
  543.     }
  544.     while ((ep = readdir(dirp)) != NULL) {
  545.         if (ep->d_name[0] == '.' &&
  546.             (NAMLEN(ep) == 1 ||
  547.              ep->d_name[1] == '.' && NAMLEN(ep) == 2))
  548.             continue;
  549.         v = newsizedstringobject(ep->d_name, NAMLEN(ep));
  550.         if (v == NULL) {
  551.             DECREF(d);
  552.             d = NULL;
  553.             break;
  554.         }
  555.         if (addlistitem(d, v) != 0) {
  556.             DECREF(v);
  557.             DECREF(d);
  558.             d = NULL;
  559.             break;
  560.         }
  561.         DECREF(v);
  562.     }
  563.     closedir(dirp);
  564.     END_SAVE
  565.  
  566.     return d;
  567.  
  568. #endif /* !NT */
  569. }
  570.  
  571. static object *
  572. posix_mkdir(self, args)
  573.     object *self;
  574.     object *args;
  575. {
  576.     return posix_strint(args, mkdir);
  577. }
  578.  
  579. #ifdef HAVE_NICE
  580. static object *
  581. posix_nice(self, args)
  582.     object *self;
  583.     object *args;
  584. {
  585.     int increment, value;
  586.  
  587.     if (!getargs(args, "i", &increment))
  588.         return NULL;
  589.     value = nice(increment);
  590.     if (value == -1)
  591.         return posix_error();
  592.     return newintobject((long) value);
  593. }
  594. #endif /* HAVE_NICE */
  595.  
  596. static object *
  597. posix_rename(self, args)
  598.     object *self;
  599.     object *args;
  600. {
  601.     return posix_2str(args, rename);
  602. }
  603.  
  604. static object *
  605. posix_rmdir(self, args)
  606.     object *self;
  607.     object *args;
  608. {
  609.     return posix_1str(args, rmdir);
  610. }
  611.  
  612. static object *
  613. posix_stat(self, args)
  614.     object *self;
  615.     object *args;
  616. {
  617.     return posix_do_stat(self, args, stat);
  618. }
  619.  
  620. static object *
  621. posix_system(self, args)
  622.     object *self;
  623.     object *args;
  624. {
  625.     char *command;
  626.     long sts;
  627.     if (!getargs(args, "s", &command))
  628.         return NULL;
  629.     BGN_SAVE
  630.     sts = system(command);
  631.     END_SAVE
  632.     return newintobject(sts);
  633. }
  634.  
  635. #ifdef HAVE_UMASK
  636. static object *
  637. posix_umask(self, args)
  638.     object *self;
  639.     object *args;
  640. {
  641.     int i;
  642.     if (!getintarg(args, &i))
  643.         return NULL;
  644.     i = umask(i);
  645.     if (i < 0)
  646.         return posix_error();
  647.     return newintobject((long)i);
  648. }
  649. #endif /* HAVE_UMASK */
  650.  
  651. static object *
  652. posix_unlink(self, args)
  653.     object *self;
  654.     object *args;
  655. {
  656.     return posix_1str(args, unlink);
  657. }
  658.  
  659. #ifdef HAVE_UNAME
  660. static object *
  661. posix_uname(self, args)
  662.     object *self;
  663.     object *args;
  664. {
  665.     struct utsname u;
  666.     object *v;
  667.     int res;
  668.     if (!getnoarg(args))
  669.         return NULL;
  670.     BGN_SAVE
  671.     res = uname(&u);
  672.     END_SAVE
  673.     if (res < 0)
  674.         return posix_error();
  675.     return mkvalue("(sssss)",
  676.                u.sysname,
  677.                u.nodename,
  678.                u.release,
  679.                u.version,
  680.                u.machine);
  681. }
  682. #endif /* HAVE_UNAME */
  683.  
  684. #ifdef HAVE_UTIME
  685. static object *
  686. posix_utime(self, args)
  687.     object *self;
  688.     object *args;
  689. {
  690.     char *path;
  691.     long atime, mtime;
  692.     int res;
  693.  
  694. #ifdef HAVE_UTIME_H
  695.     struct utimbuf buf;
  696. #define ATIME buf.actime
  697. #define MTIME buf.modtime
  698. #define UTIME_ARG &buf
  699. #else /* HAVE_UTIME_H */
  700.     time_t buf[2];
  701. #define ATIME buf[0]
  702. #define MTIME buf[1]
  703. #define UTIME_ARG buf
  704. #endif /* HAVE_UTIME_H */
  705.  
  706.     if (!getargs(args, "(s(ll))", &path, &atime, &mtime))
  707.         return NULL;
  708.     ATIME = atime;
  709.     MTIME = mtime;
  710.     BGN_SAVE
  711.     res = utime(path, UTIME_ARG);
  712.     END_SAVE
  713.     if (res < 0)
  714.         return posix_error();
  715.     INCREF(None);
  716.     return None;
  717. #undef UTIME_ARG
  718. #undef ATIME
  719. #undef MTIME
  720. }
  721. #endif /* HAVE_UTIME */
  722.  
  723.  
  724. /* Process operations */
  725.  
  726. static object *
  727. posix__exit(self, args)
  728.     object *self;
  729.     object *args;
  730. {
  731.     int sts;
  732.     if (!getintarg(args, &sts))
  733.         return NULL;
  734.     _exit(sts);
  735.     /* NOTREACHED */
  736. }
  737. #ifdef HAVE_FORK
  738. static object *
  739. posix_execv(self, args)
  740.     object *self;
  741.     object *args;
  742. {
  743.     char *path;
  744.     object *argv;
  745.     char **argvlist;
  746.     int i, argc;
  747.     object *(*getitem) PROTO((object *, int));
  748.  
  749.     /* execv has two arguments: (path, argv), where
  750.        argv is a list or tuple of strings. */
  751.  
  752.     if (!getargs(args, "(sO)", &path, &argv))
  753.         return NULL;
  754.     if (is_listobject(argv)) {
  755.         argc = getlistsize(argv);
  756.         getitem = getlistitem;
  757.     }
  758.     else if (is_tupleobject(argv)) {
  759.         argc = gettuplesize(argv);
  760.         getitem = gettupleitem;
  761.     }
  762.     else {
  763.  badarg:
  764.         err_badarg();
  765.         return NULL;
  766.     }
  767.  
  768.     argvlist = NEW(char *, argc+1);
  769.     if (argvlist == NULL)
  770.         return NULL;
  771.     for (i = 0; i < argc; i++) {
  772.         if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
  773.             DEL(argvlist);
  774.             goto badarg;
  775.         }
  776.     }
  777.     argvlist[argc] = NULL;
  778.  
  779. #ifdef BAD_EXEC_PROTOTYPES
  780.     execv(path, (const char **) argvlist);
  781. #else /* BAD_EXEC_PROTOTYPES */
  782.     execv(path, argvlist);
  783. #endif /* BAD_EXEC_PROTOTYPES */
  784.  
  785.     /* If we get here it's definitely an error */
  786.  
  787.     DEL(argvlist);
  788.     return posix_error();
  789. }
  790.  
  791. static object *
  792. posix_execve(self, args)
  793.     object *self;
  794.     object *args;
  795. {
  796.     char *path;
  797.     object *argv, *env;
  798.     char **argvlist;
  799.     char **envlist;
  800.     object *key, *val;
  801.     int i, pos, argc, envc;
  802.     object *(*getitem) PROTO((object *, int));
  803.  
  804.     /* execve has three arguments: (path, argv, env), where
  805.        argv is a list or tuple of strings and env is a dictionary
  806.        like posix.environ. */
  807.  
  808.     if (!getargs(args, "(sOO)", &path, &argv, &env))
  809.         return NULL;
  810.     if (is_listobject(argv)) {
  811.         argc = getlistsize(argv);
  812.         getitem = getlistitem;
  813.     }
  814.     else if (is_tupleobject(argv)) {
  815.         argc = gettuplesize(argv);
  816.         getitem = gettupleitem;
  817.     }
  818.     else {
  819.         err_setstr(TypeError, "argv must be tuple or list");
  820.         return NULL;
  821.     }
  822.     if (!is_dictobject(env)) {
  823.         err_setstr(TypeError, "env must be dictionary");
  824.         return NULL;
  825.     }
  826.  
  827.     argvlist = NEW(char *, argc+1);
  828.     if (argvlist == NULL) {
  829.         err_nomem();
  830.         return NULL;
  831.     }
  832.     for (i = 0; i < argc; i++) {
  833.         if (!getargs((*getitem)(argv, i),
  834.                  "s;argv must be list of strings",
  835.                  &argvlist[i])) {
  836.             goto fail_1;
  837.         }
  838.     }
  839.     argvlist[argc] = NULL;
  840.  
  841.     i = getmappingsize(env);
  842.     envlist = NEW(char *, i + 1);
  843.     if (envlist == NULL) {
  844.         err_nomem();
  845.         goto fail_1;
  846.     }
  847.     pos = 0;
  848.     envc = 0;
  849.     while (mappinggetnext(env, &pos, &key, &val)) {
  850.         char *p, *k, *v;
  851.         if (!getargs(key, "s;non-string key in env", &k) ||
  852.             !getargs(val, "s;non-string value in env", &v)) {
  853.             goto fail_2;
  854.         }
  855.         p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
  856.         if (p == NULL) {
  857.             err_nomem();
  858.             goto fail_2;
  859.         }
  860.         sprintf(p, "%s=%s", k, v);
  861.         envlist[envc++] = p;
  862.     }
  863.     envlist[envc] = 0;
  864.  
  865.  
  866. #ifdef BAD_EXEC_PROTOTYPES
  867.     execve(path, (const char **)argvlist, envlist);
  868. #else /* BAD_EXEC_PROTOTYPES */
  869.     execve(path, argvlist, envlist);
  870. #endif /* BAD_EXEC_PROTOTYPES */
  871.     
  872.     /* If we get here it's definitely an error */
  873.  
  874.     (void) posix_error();
  875.  
  876.  fail_2:
  877.     while (--envc >= 0)
  878.         DEL(envlist[envc]);
  879.     DEL(envlist);
  880.  fail_1:
  881.     DEL(argvlist);
  882.  
  883.     return NULL;
  884. }
  885.  
  886. static object *
  887. posix_fork(self, args)
  888.     object *self;
  889.     object *args;
  890. {
  891.     int pid;
  892.     if (!getnoarg(args))
  893.         return NULL;
  894.     pid = fork();
  895.     if (pid == -1)
  896.         return posix_error();
  897.     return newintobject((long)pid);
  898. }
  899. #endif /* HAVE_FORK */
  900.  
  901. #ifdef HAVE_GETEGID
  902. static object *
  903. posix_getegid(self, args)
  904.     object *self;
  905.     object *args;
  906. {
  907.     if (!getnoarg(args))
  908.         return NULL;
  909.     return newintobject((long)getegid());
  910. }
  911. #endif
  912.  
  913. #ifdef HAVE_GETEUID
  914. static object *
  915. posix_geteuid(self, args)
  916.     object *self;
  917.     object *args;
  918. {
  919.     if (!getnoarg(args))
  920.         return NULL;
  921.     return newintobject((long)geteuid());
  922. }
  923. #endif
  924.  
  925. #ifdef HAVE_GETGID
  926. static object *
  927. posix_getgid(self, args)
  928.     object *self;
  929.     object *args;
  930. {
  931.     if (!getnoarg(args))
  932.         return NULL;
  933.     return newintobject((long)getgid());
  934. }
  935. #endif
  936.  
  937. #ifdef HAVE_GETPID
  938. static object *
  939. posix_getpid(self, args)
  940.     object *self;
  941.     object *args;
  942. {
  943.     if (!getnoarg(args))
  944.         return NULL;
  945.     return newintobject((long)getpid());
  946. }
  947. #endif
  948.  
  949. #ifdef HAVE_GETPGRP
  950. static object *
  951. posix_getpgrp(self, args)
  952.     object *self;
  953.     object *args;
  954. {
  955.     if (!getnoarg(args))
  956.         return NULL;
  957. #ifdef GETPGRP_HAVE_ARG
  958.     return newintobject((long)getpgrp(0));
  959. #else /* GETPGRP_HAVE_ARG */
  960.     return newintobject((long)getpgrp());
  961. #endif /* GETPGRP_HAVE_ARG */
  962. }
  963. #endif /* HAVE_GETPGRP */
  964.  
  965. #ifdef HAVE_SETPGRP
  966. static object *
  967. posix_setpgrp(self, args)
  968.     object *self;
  969.     object *args;
  970. {
  971.     if (!getnoarg(args))
  972.         return NULL;
  973. #ifdef SETPGRP_HAVE_ARG
  974.     if (setpgrp(0, 0) < 0)
  975. #else /* SETPGRP_HAVE_ARG */
  976.     if (setpgrp() < 0)
  977. #endif /* SETPGRP_HAVE_ARG */
  978.         return posix_error();
  979.     INCREF(None);
  980.     return None;
  981. }
  982.  
  983. #endif /* HAVE_SETPGRP */
  984.  
  985. #ifdef HAVE_GETPPID
  986. static object *
  987. posix_getppid(self, args)
  988.     object *self;
  989.     object *args;
  990. {
  991.     if (!getnoarg(args))
  992.         return NULL;
  993.     return newintobject((long)getppid());
  994. }
  995. #endif
  996.  
  997. #ifdef HAVE_GETUID
  998. static object *
  999. posix_getuid(self, args)
  1000.     object *self;
  1001.     object *args;
  1002. {
  1003.     if (!getnoarg(args))
  1004.         return NULL;
  1005.     return newintobject((long)getuid());
  1006. }
  1007. #endif
  1008.  
  1009. #ifdef HAVE_KILL
  1010. static object *
  1011. posix_kill(self, args)
  1012.     object *self;
  1013.     object *args;
  1014. {
  1015.     int pid, sig;
  1016.     if (!getargs(args, "(ii)", &pid, &sig))
  1017.         return NULL;
  1018.     if (kill(pid, sig) == -1)
  1019.         return posix_error();
  1020.     INCREF(None);
  1021.     return None;
  1022. }
  1023. #endif
  1024. #ifdef HAVE_PIPE
  1025. static object *
  1026. posix_popen(self, args)
  1027.     object *self;
  1028.     object *args;
  1029. {
  1030.     char *name;
  1031.     char *mode = "r";
  1032.     int bufsize = -1;
  1033.     FILE *fp;
  1034.     object *f;
  1035.     if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
  1036.         return NULL;
  1037.     BGN_SAVE
  1038.     fp = popen(name, mode);
  1039.     END_SAVE
  1040.     if (fp == NULL)
  1041.         return posix_error();
  1042.     f = newopenfileobject(fp, name, mode, pclose);
  1043.     if (f != NULL)
  1044.         setfilebufsize(f, bufsize);
  1045.     return f;
  1046. }
  1047. #endif /* HAVE_PIPE */
  1048.  
  1049. #ifdef HAVE_SETUID
  1050. static object *
  1051. posix_setuid(self, args)
  1052.     object *self;
  1053.     object *args;
  1054. {
  1055.     int uid;
  1056.     if (!getargs(args, "i", &uid))
  1057.         return NULL;
  1058.     if (setuid(uid) < 0)
  1059.         return posix_error();
  1060.     INCREF(None);
  1061.     return None;
  1062. }
  1063. #endif /* HAVE_SETUID */
  1064.  
  1065. #ifdef HAVE_SETGID
  1066. static object *
  1067. posix_setgid(self, args)
  1068.     object *self;
  1069.     object *args;
  1070. {
  1071.     int gid;
  1072.     if (!getargs(args, "i", &gid))
  1073.         return NULL;
  1074.     if (setgid(gid) < 0)
  1075.         return posix_error();
  1076.     INCREF(None);
  1077.     return None;
  1078. }
  1079. #endif /* HAVE_SETGID */
  1080.  
  1081. #ifdef HAVE_WAITPID
  1082. static object *
  1083. posix_waitpid(self, args)
  1084.     object *self;
  1085.     object *args;
  1086. {
  1087.     int pid, options, sts;
  1088.     if (!getargs(args, "(ii)", &pid, &options))
  1089.         return NULL;
  1090.     BGN_SAVE
  1091.     pid = waitpid(pid, &sts, options);
  1092.     END_SAVE
  1093.     if (pid == -1)
  1094.         return posix_error();
  1095.     else
  1096.         return mkvalue("ii", pid, sts);
  1097. }
  1098. #endif /* HAVE_WAITPID */
  1099.  
  1100. #ifdef HAVE_WAIT
  1101. static object *
  1102. posix_wait(self, args)
  1103.     object *self;
  1104.     object *args;
  1105. {
  1106.     int pid, sts;
  1107.     BGN_SAVE
  1108.     pid = wait(&sts);
  1109.     END_SAVE
  1110.     if (pid == -1)
  1111.         return posix_error();
  1112.     else
  1113.         return mkvalue("ii", pid, sts);
  1114. }
  1115. #endif
  1116.  
  1117. static object *
  1118. posix_lstat(self, args)
  1119.     object *self;
  1120.     object *args;
  1121. {
  1122. #ifdef HAVE_LSTAT
  1123.     return posix_do_stat(self, args, lstat);
  1124. #else /* !HAVE_LSTAT */
  1125.     return posix_do_stat(self, args, stat);
  1126. #endif /* !HAVE_LSTAT */
  1127. }
  1128.  
  1129. #ifdef HAVE_READLINK
  1130. static object *
  1131. posix_readlink(self, args)
  1132.     object *self;
  1133.     object *args;
  1134. {
  1135.     char buf[MAXPATHLEN];
  1136.     char *path;
  1137.     int n;
  1138.     if (!getargs(args, "s", &path))
  1139.         return NULL;
  1140.     BGN_SAVE
  1141.     n = readlink(path, buf, (int) sizeof buf);
  1142.     END_SAVE
  1143.     if (n < 0)
  1144.         return posix_error();
  1145.     return newsizedstringobject(buf, n);
  1146. }
  1147. #endif /* HAVE_READLINK */
  1148.  
  1149. #ifdef HAVE_SYMLINK
  1150. static object *
  1151. posix_symlink(self, args)
  1152.     object *self;
  1153.     object *args;
  1154. {
  1155.     return posix_2str(args, symlink);
  1156. }
  1157. #endif /* HAVE_SYMLINK */
  1158.  
  1159. #ifdef HAVE_TIMES
  1160. #ifndef HZ
  1161. #define HZ 60 /* Universal constant :-) */
  1162. #endif /* HZ */
  1163. static object *
  1164. posix_times(self, args)
  1165.     object *self;
  1166.     object *args;
  1167. {
  1168.     struct tms t;
  1169.     clock_t c;
  1170.     if (!getnoarg(args))
  1171.         return NULL;
  1172.     errno = 0;
  1173.     c = times(&t);
  1174.     if (c == (clock_t) -1)
  1175.         return posix_error();
  1176.     return mkvalue("ddddd",
  1177.                (double)t.tms_utime / HZ,
  1178.                (double)t.tms_stime / HZ,
  1179.                (double)t.tms_cutime / HZ,
  1180.                (double)t.tms_cstime / HZ,
  1181.                (double)c / HZ);
  1182. }
  1183. #endif /* HAVE_TIMES */
  1184. #if defined(NT) && !defined(HAVE_TIMES)
  1185. #define HAVE_TIMES    /* so the method table will pick it up */
  1186. static object *
  1187. posix_times(self, args)
  1188.     object *self;
  1189.     object *args;
  1190. {
  1191.     FILETIME create, exit, kernel, user;
  1192.     HANDLE hProc;
  1193.     if (!getnoarg(args))
  1194.         return NULL;
  1195.     hProc = GetCurrentProcess();
  1196.     GetProcessTimes(hProc,&create, &exit, &kernel, &user);
  1197.     return mkvalue("ddddd",
  1198.                (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
  1199.                (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
  1200.                (double)0,
  1201.                (double)0,
  1202.                (double)0);
  1203. }
  1204. #endif /* NT */
  1205.  
  1206. #ifdef HAVE_SETSID
  1207. static object *
  1208. posix_setsid(self, args)
  1209.     object *self;
  1210.     object *args;
  1211. {
  1212.     if (!getnoarg(args))
  1213.         return NULL;
  1214.     if (setsid() < 0)
  1215.         return posix_error();
  1216.     INCREF(None);
  1217.     return None;
  1218. }
  1219. #endif /* HAVE_SETSID */
  1220.  
  1221. #ifdef HAVE_SETPGID
  1222. static object *
  1223. posix_setpgid(self, args)
  1224.     object *self;
  1225.     object *args;
  1226. {
  1227.     int pid, pgrp;
  1228.     if (!getargs(args, "(ii)", &pid, &pgrp))
  1229.         return NULL;
  1230.     if (setpgid(pid, pgrp) < 0)
  1231.         return posix_error();
  1232.     INCREF(None);
  1233.     return None;
  1234. }
  1235. #endif /* HAVE_SETPGID */
  1236.  
  1237. #ifdef HAVE_TCGETPGRP
  1238. static object *
  1239. posix_tcgetpgrp(self, args)
  1240.     object *self;
  1241.     object *args;
  1242. {
  1243.     int fd, pgid;
  1244.     if (!getargs(args, "i", &fd))
  1245.         return NULL;
  1246.     pgid = tcgetpgrp(fd);
  1247.     if (pgid < 0)
  1248.         return posix_error();
  1249.     return newintobject((long)pgid);
  1250. }
  1251. #endif /* HAVE_TCGETPGRP */
  1252.  
  1253. #ifdef HAVE_TCSETPGRP
  1254. static object *
  1255. posix_tcsetpgrp(self, args)
  1256.     object *self;
  1257.     object *args;
  1258. {
  1259.     int fd, pgid;
  1260.     if (!getargs(args, "(ii)", &fd, &pgid))
  1261.         return NULL;
  1262.     if (tcsetpgrp(fd, pgid) < 0)
  1263.         return posix_error();
  1264.        INCREF(None);
  1265.     return None;
  1266. }
  1267. #endif /* HAVE_TCSETPGRP */
  1268.  
  1269. /* Functions acting on file descriptors */
  1270.  
  1271. static object *
  1272. posix_open(self, args)
  1273.     object *self;
  1274.     object *args;
  1275. {
  1276.     char *file;
  1277.     int flag;
  1278.     int mode = 0777;
  1279.     int fd;
  1280.     if (!getargs(args, "(si)", &file, &flag)) {
  1281.         err_clear();
  1282.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  1283.             return NULL;
  1284.     }
  1285.     BGN_SAVE
  1286.     fd = open(file, flag, mode);
  1287.     END_SAVE
  1288.     if (fd < 0)
  1289.         return posix_error();
  1290.     return newintobject((long)fd);
  1291. }
  1292.  
  1293. static object *
  1294. posix_close(self, args)
  1295.     object *self;
  1296.     object *args;
  1297. {
  1298.     int fd, res;
  1299.     if (!getargs(args, "i", &fd))
  1300.         return NULL;
  1301.     BGN_SAVE
  1302.     res = close(fd);
  1303.     END_SAVE
  1304.     if (res < 0)
  1305.         return posix_error();
  1306.     INCREF(None);
  1307.     return None;
  1308. }
  1309.  
  1310. #ifdef HAVE_DUP
  1311. static object *
  1312. posix_dup(self, args)
  1313.     object *self;
  1314.     object *args;
  1315. {
  1316.     int fd;
  1317.     if (!getargs(args, "i", &fd))
  1318.         return NULL;
  1319.     BGN_SAVE
  1320.     fd = dup(fd);
  1321.     END_SAVE
  1322.     if (fd < 0)
  1323.         return posix_error();
  1324.     return newintobject((long)fd);
  1325. }
  1326.  
  1327. static object *
  1328. posix_dup2(self, args)
  1329.     object *self;
  1330.     object *args;
  1331. {
  1332.     int fd, fd2, res;
  1333.     if (!getargs(args, "(ii)", &fd, &fd2))
  1334.         return NULL;
  1335.     BGN_SAVE
  1336.     res = dup2(fd, fd2);
  1337.     END_SAVE
  1338.     if (res < 0)
  1339.         return posix_error();
  1340.     INCREF(None);
  1341.     return None;
  1342. }
  1343. #endif /* HAVE_DUP */
  1344.  
  1345. static object *
  1346. posix_lseek(self, args)
  1347.     object *self;
  1348.     object *args;
  1349. {
  1350.     int fd, how;
  1351.     long pos, res;
  1352.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  1353.         return NULL;
  1354. #ifdef SEEK_SET
  1355.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  1356.     switch (how) {
  1357.     case 0: how = SEEK_SET; break;
  1358.     case 1: how = SEEK_CUR; break;
  1359.     case 2: how = SEEK_END; break;
  1360.     }
  1361. #endif /* SEEK_END */
  1362.     BGN_SAVE
  1363.     res = lseek(fd, pos, how);
  1364.     END_SAVE
  1365.     if (res < 0)
  1366.         return posix_error();
  1367.     return newintobject(res);
  1368. }
  1369.  
  1370. static object *
  1371. posix_read(self, args)
  1372.     object *self;
  1373.     object *args;
  1374. {
  1375.     int fd, size;
  1376.     object *buffer;
  1377.     if (!getargs(args, "(ii)", &fd, &size))
  1378.         return NULL;
  1379.     buffer = newsizedstringobject((char *)NULL, size);
  1380.     if (buffer == NULL)
  1381.         return NULL;
  1382.     BGN_SAVE
  1383.     size = read(fd, getstringvalue(buffer), size);
  1384.     END_SAVE
  1385.     if (size < 0) {
  1386.         DECREF(buffer);
  1387.         return posix_error();
  1388.     }
  1389.     resizestring(&buffer, size);
  1390.     return buffer;
  1391. }
  1392.  
  1393. static object *
  1394. posix_write(self, args)
  1395.     object *self;
  1396.     object *args;
  1397. {
  1398.     int fd, size;
  1399.     char *buffer;
  1400.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  1401.         return NULL;
  1402.     BGN_SAVE
  1403.     size = write(fd, buffer, size);
  1404.     END_SAVE
  1405.     if (size < 0)
  1406.         return posix_error();
  1407.     return newintobject((long)size);
  1408. }
  1409.  
  1410. static object *
  1411. posix_fstat(self, args)
  1412.     object *self;
  1413.     object *args;
  1414. {
  1415.     int fd;
  1416.     struct stat st;
  1417.     int res;
  1418.     if (!getargs(args, "i", &fd))
  1419.         return NULL;
  1420.     BGN_SAVE
  1421.     res = fstat(fd, &st);
  1422.     END_SAVE
  1423.     if (res != 0)
  1424.         return posix_error();
  1425.     return mkvalue("(llllllllll)",
  1426.             (long)st.st_mode,
  1427.             (long)st.st_ino,
  1428.             (long)st.st_dev,
  1429.             (long)st.st_nlink,
  1430.             (long)st.st_uid,
  1431.             (long)st.st_gid,
  1432.             (long)st.st_size,
  1433.             (long)st.st_atime,
  1434.             (long)st.st_mtime,
  1435.             (long)st.st_ctime);
  1436. }
  1437.  
  1438. static object *
  1439. posix_fdopen(self, args)
  1440.     object *self;
  1441.     object *args;
  1442. {
  1443.     extern int fclose PROTO((FILE *));
  1444.     int fd;
  1445.     char *mode = "r";
  1446.     int bufsize = -1;
  1447.     FILE *fp;
  1448.     object *f;
  1449.     if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
  1450.         return NULL;
  1451.     BGN_SAVE
  1452.     fp = fdopen(fd, mode);
  1453.     END_SAVE
  1454.     if (fp == NULL)
  1455.         return posix_error();
  1456.     f = newopenfileobject(fp, "(fdopen)", mode, fclose);
  1457.     if (f != NULL)
  1458.         setfilebufsize(f, bufsize);
  1459.     return f;
  1460. }
  1461. #ifdef HAVE_PIPE
  1462. static object *
  1463. posix_pipe(self, args)
  1464.     object *self;
  1465.     object *args;
  1466. {
  1467. #if !defined(NT) || defined(HAVE_PIPE)
  1468.     int fds[2];
  1469.     int res;
  1470.     if (!getargs(args, ""))
  1471.         return NULL;
  1472.     BGN_SAVE
  1473.     res = pipe(fds);
  1474.     END_SAVE
  1475.     if (res != 0)
  1476.         return posix_error();
  1477.     return mkvalue("(ii)", fds[0], fds[1]);
  1478. #else /* NT */
  1479.     HANDLE read, write;
  1480.     BOOL ok;
  1481.     if (!getargs(args, ""))
  1482.         return NULL;
  1483.     BGN_SAVE
  1484.     ok = CreatePipe( &read, &write, NULL, 0);
  1485.     END_SAVE
  1486.     if (!ok)
  1487.         return posix_error();
  1488.     return mkvalue("(ii)", read, write);
  1489. #endif /* NT */
  1490. }
  1491. #endif /* HAVE_PIPE */
  1492.  
  1493. static struct methodlist posix_methods[] = {
  1494.     {"chdir",    posix_chdir},
  1495.     {"chmod",    posix_chmod},
  1496. #ifdef HAVE_CHOWN
  1497.     {"chown",    posix_chown},
  1498. #endif /* HAVE_CHOWN */
  1499. #ifdef HAVE_GETCWD
  1500.     {"getcwd",    posix_getcwd},
  1501. #endif
  1502. #ifdef HAVE_LINK
  1503.     {"link",    posix_link},
  1504. #endif /* HAVE_LINK */
  1505.     {"listdir",    posix_listdir},
  1506.     {"lstat",    posix_lstat},
  1507.     {"mkdir",    posix_mkdir},
  1508. #ifdef HAVE_NICE
  1509.     {"nice",    posix_nice},
  1510. #endif /* HAVE_NICE */
  1511. #ifdef HAVE_READLINK
  1512.     {"readlink",    posix_readlink},
  1513. #endif /* HAVE_READLINK */
  1514.     {"rename",    posix_rename},
  1515.     {"rmdir",    posix_rmdir},
  1516.     {"stat",    posix_stat},
  1517. #ifdef HAVE_SYMLINK
  1518.     {"symlink",    posix_symlink},
  1519. #endif /* HAVE_SYMLINK */
  1520.     {"system",    posix_system},
  1521. #ifdef HAVE_UMASK
  1522.     {"umask",    posix_umask},
  1523. #endif /* HAVE_UMASK */
  1524. #ifdef HAVE_UNAME
  1525.     {"uname",    posix_uname},
  1526. #endif /* HAVE_UNAME */
  1527.     {"unlink",    posix_unlink},
  1528. #ifdef HAVE_UTIME
  1529.     {"utime",    posix_utime},
  1530. #endif /* HAVE_UTIME */
  1531. #ifdef HAVE_TIMES
  1532.     {"times",    posix_times},
  1533. #endif /* HAVE_TIMES */
  1534.     {"_exit",    posix__exit},
  1535. #ifdef HAVE_FORK
  1536.     {"execv",    posix_execv},
  1537. #endif /* HAVE_EXECV */
  1538. #ifdef HAVE_FORK
  1539.     {"execve",    posix_execve},
  1540. #endif /* HAVE_EXECVE */
  1541. #ifdef HAVE_FORK
  1542.     {"fork",    posix_fork},
  1543. #endif /* HAVE_FORK */
  1544. #ifdef HAVE_GETEGID
  1545.     {"getegid",    posix_getegid},
  1546. #endif /* HAVE_GETEGID */
  1547. #ifdef HAVE_GETEUID
  1548.     {"geteuid",    posix_geteuid},
  1549. #endif /* HAVE_GETEUID */
  1550. #ifdef HAVE_GETGID
  1551.     {"getgid",    posix_getgid},
  1552. #endif /* HAVE_GETGID */
  1553. #ifdef HAVE_GETPID
  1554.     {"getpid",    posix_getpid},
  1555. #else /* HAVE_GETPID */
  1556. #ifdef HAVE_GETPGRP
  1557.     {"getpgrp",    posix_getpgrp},
  1558. #endif /* HAVE_GETPGRP */
  1559. #ifdef HAVE_GETPPID
  1560.     {"getppid",    posix_getppid},
  1561. #endif /* HAVE_GETPPID */
  1562. #ifdef HAVE_GETUID
  1563.     {"getuid",    posix_getuid},
  1564. #endif /* HAVE_GETUID */
  1565. #ifdef HAVE_KILL
  1566.     {"kill",    posix_kill},
  1567. #endif /* HAVE_KILL */
  1568. #ifdef HAVE_PIPE
  1569.     {"popen",    posix_popen,    1},
  1570. #else /* HAVE_PIPE */
  1571. #ifdef HAVE_SETUID
  1572.     {"setuid",    posix_setuid},
  1573. #endif /* HAVE_SETUID */
  1574. #ifdef HAVE_SETGID
  1575.     {"setgid",    posix_setgid},
  1576. #endif /* HAVE_SETGID */
  1577. #ifdef HAVE_SETPGRP
  1578.     {"setpgrp",    posix_setpgrp},
  1579. #endif /* HAVE_SETPGRP */
  1580. #ifdef HAVE_WAIT
  1581.     {"wait",    posix_wait},
  1582. #endif /* HAVE_WAIT */
  1583. #ifdef HAVE_WAITPID
  1584.     {"waitpid",    posix_waitpid},
  1585. #endif /* HAVE_WAITPID */
  1586. #ifdef HAVE_SETSID
  1587.     {"setsid",    posix_setsid},
  1588. #endif /* HAVE_SETSID */
  1589. #ifdef HAVE_SETPGID
  1590.     {"setpgid",    posix_setpgid},
  1591. #endif /* HAVE_SETPGID */
  1592. #ifdef HAVE_TCGETPGRP
  1593.     {"tcgetpgrp",    posix_tcgetpgrp},
  1594. #endif /* HAVE_TCGETPGRP */
  1595. #ifdef HAVE_TCSETPGRP
  1596.     {"tcsetpgrp",    posix_tcsetpgrp},
  1597. #endif /* HAVE_TCSETPGRP */
  1598.     {"open",    posix_open},
  1599.     {"close",    posix_close},
  1600. #ifdef HAVE_DUP
  1601.     {"dup",        posix_dup},
  1602.     {"dup2",    posix_dup2},
  1603. #else /* HAVE_DUP */
  1604.     {"lseek",    posix_lseek},
  1605.     {"read",    posix_read},
  1606.     {"write",    posix_write},
  1607. #ifdef HAVE_FSTAT
  1608.     {"fstat",    posix_fstat},
  1609. #endif /* HAVE_FSTAT */
  1610.     {"fdopen",    posix_fdopen,    1},
  1611. #ifdef HAVE_PIPE
  1612.     {"pipe",    posix_pipe},
  1613. #endif /* HAVE_PIPE */
  1614.     {NULL,        NULL}         /* Sentinel */
  1615. };
  1616.  
  1617.  
  1618. #ifdef NT
  1619. void
  1620. initnt()
  1621. {
  1622.     object *m, *d, *v;
  1623.     
  1624.     m = initmodule("nt", posix_methods);
  1625.     d = getmoduledict(m);
  1626.     
  1627.     /* Initialize nt.environ dictionary */
  1628.     v = convertenviron();
  1629.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1630.         fatal("can't define nt.environ");
  1631.     DECREF(v);
  1632.     
  1633.     /* Initialize nt.error exception */
  1634.     PosixError = newstringobject("nt.error");
  1635.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1636.         fatal("can't define nt.error");
  1637. }
  1638. #else /* !NT */
  1639. void
  1640. initposix()
  1641. {
  1642.     object *m, *d, *v;
  1643.     
  1644.     m = initmodule("posix", posix_methods);
  1645.     d = getmoduledict(m);
  1646.     
  1647.     /* Initialize posix.environ dictionary */
  1648.     v = convertenviron();
  1649.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1650.         fatal("can't define posix.environ");
  1651.     DECREF(v);
  1652.     
  1653. #ifdef WNOHANG
  1654.     /* Export WNOHANG symbol */
  1655.     v = newintobject((long)WNOHANG);
  1656.     if (v == NULL || dictinsert(d, "WNOHANG", v) != 0)
  1657.         fatal("can't define posix.WNOHANG");
  1658.     DECREF(v);
  1659. #endif
  1660.     
  1661.     /* Initialize posix.error exception */
  1662.     PosixError = newstringobject("posix.error");
  1663.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1664.         fatal("can't define posix.error");
  1665. }
  1666. #endif /* !NT */
  1667.